#include "JSerialize.h"
#include <boost/foreach.hpp>
#include <fstream>




JSerialize::JSerialize(void)
{
}


JSerialize::~JSerialize(void)
{
}


//classSize is the data size.
//selfSize is the int size add classSize
//allSize is allSize += selfSize
int JSerialize::PutChars( std::iostream& strea,const char* c,int n,int& allSize)
{
	int classSize = 0;
	int selfSize = 0;
	strea.write(c,n);
	classSize += n;
	selfSize = classSize;
	allSize += selfSize;
	return selfSize;
}

int JSerialize::PutInt( std::iostream& strea,int i,int& allSize)
{
	int classSize = 0;
	int selfSize = 0;
	strea.write((char*)&i,sizeof(int));
	classSize += sizeof(int);
	selfSize = classSize;
	allSize += selfSize;
	return selfSize;
}

int JSerialize::Serialize( std::iostream& strea,int i ,int& allSize)
{
	int classSize = 0;
	int selfSize = 0;
	PutInt(strea,sizeof(int),selfSize);
	PutInt(strea,i,classSize);
	selfSize += classSize;
	allSize += selfSize;
	return selfSize;
}

int JSerialize::Serialize( std::iostream& strea,std::string s ,int& allSize)
{
	int classSize = 0;
	int selfSize = 0;
	PutInt(strea,s.length(),selfSize);
	PutChars(strea,s.c_str(),s.length(),classSize);
	selfSize += classSize;
	allSize += selfSize;
	return selfSize;
}

/*
data structor:
int :vec.size()*sizeof(int)
int : ....
*/
int JSerialize::Serialize(std::iostream& strea,std::vector<int> vec,int& allSize)
{
	int classSize = 0;
	int selfSize = 0;
	PutInt(strea,vec.size(),selfSize);
	for(int i = 0;i < vec.size(); ++i)
	{
		PutInt(strea,vec[i],classSize);
	}
	selfSize += classSize;
	allSize += selfSize;
	return selfSize;
}

int JSerialize::Serialize( std::iostream& _strea,std::list<std::string> strList ,int& allSize)
{
	int classSize = 0;
	int selfSize = 0;
	PutInt(_strea,strList.size(),selfSize);
	BOOST_FOREACH(std::string& s,strList)
	{
		Serialize(_strea,s,classSize); 
	}
	selfSize += classSize;
	allSize += selfSize;
	return selfSize;
}

int JSerialize::Serialize( std::iostream& _strea,std::fstream& _fs,int& _allSize )
{
	int fileSize = 0;
	int classSize = 0,selfSize = 0;
	PutInt(_strea,fileSize,selfSize);
	char buff[1024];
	while(_fs.good())
	{
		memset(buff,0,1024);
		_fs.read(buff,1024);
		int n = _fs.gcount();
		fileSize += n;
		_strea.write(buff,n);
	}
	classSize += fileSize;
	selfSize += classSize;
	JSerialize::Verify(_strea,classSize,-1*selfSize);
	_allSize += selfSize;
	return selfSize;
}

void JSerialize::Verify( std::iostream& _strea,int _data,int _offSize )
{
	int tmp;
	_strea.seekp(_offSize,std::ios::cur);
	PutInt(_strea,_data,tmp);
	_strea.seekp(0,std::ios::end);
	//_strea.seekp((_offSize - sizeof(int))*-1,std::ios::cur);
}

int JSerialize::GetInt( std::iostream& _strea ,int intSize)
{
	int i;
	_strea.read((char*)&i,sizeof(int));
	return i;
}

int JSerialize::ReSerializeInt(std::iostream& strea)
{
	int classSize = GetInt(strea,sizeof(int));
	int i = GetInt(strea,classSize);
	return i;
}

std::string JSerialize::ReSerializeString( std::iostream& _strea )
{
	int classSize = JSerialize::GetInt(_strea,sizeof(int));
	char* tmp = new char[classSize + 1];
	_strea.read(tmp,classSize);
	tmp[classSize] = '\0';
	std::string s(tmp);
	delete[] tmp;
	return s;
}

std::vector<int> JSerialize::ReSerializeIntArray(std::iostream& strea)
{
	int classSize = GetInt(strea,sizeof(int));
	int count = classSize;
	std::vector<int> vec;
	for(int i = 0;i < count; ++i)
	{
		int tmpInt = GetInt(strea,sizeof(int));
		vec.push_back(tmpInt);
	}
	return vec;
}

std::list<std::string> JSerialize::ReSerializeStringList( std::iostream& strea )
{
	std::list<std::string> strList;
	int classSize = GetInt(strea,sizeof(int));
	int listSize = classSize;
	for(int i = 0;i < listSize; ++i)
	{
		std::string s = ReSerializeString(strea);
		strList.push_back(s);
	}
	return strList;
}

std::iostream& JSerialize::InitStream( std::string fileName )
{
	std::filebuf* pFb = new std::filebuf;
	pFb->open(fileName.c_str(),std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc);
	std::iostream* pStrea = new std::iostream(pFb);
	return *pStrea;
}


void JSerialize::ReSerializeFstream( std::iostream& _strea,std::fstream& _fs )
{

	int fileSize = GetInt(_strea,sizeof(int));
	char buff[1024];
	while(fileSize > 0)
	{
		_strea.read(buff,1024);
		int n = _strea.gcount();
		_fs.write(buff,n);
		fileSize -= n;
	}
}

